use std::fmt;

#[cfg(test)]
mod test_self {
    trait Draw {
        fn draw(&self) -> Self;
    }

    #[derive(Clone, Debug)]
    struct Button;

    impl Draw for Button {
        fn draw(&self) -> Self {
            return self.clone();
        }
    }

    // self --> 对象实例
    // Self --> 一个指代特征或者方法类型的别名

    #[test]
    fn main() {
        let button = Button;
        let newb = button.draw();

        println!("{:?}", newb)
    }
}
/*
特征对象的限制
不是所有特征都能拥有特征对象，只有对象安全的特征才行。当一个特征的所有方法都有如下属性时，它的对象才是安全的：
    方法的返回类型不能是 Self
    方法没有任何泛型参数
*/

// 关联类型和关联函数并没有任何交集，虽然它们的名字有一半的交集。
pub trait Iterator {
    type Item;
    // 同时，next 方法也返回了一个 Item 类型，不过使用 Option 枚举进行了包裹，
    // 假如迭代器中的值是 i32 类型，那么调用 next 方法就将获取一个 Option<i32> 的值。

    // Self 用来指代当前调用者的具体类型，那么 Self::Item 就用来指代该类型实现中定义的 Item 类型

    fn next(&mut self) -> Option<Self::Item>;
}

pub trait IteratorNew {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

pub trait CacheableItem: Clone + Default + fmt::Debug {
    type Address: AsRef<[u8]> + Clone + fmt::Debug + Eq;
    // 相当于 接口组别名
    fn is_null(&self) -> bool;
    fn next(&mut self) -> Option<Self::Address>;
}

trait Container {
    type Output;
    // 默认的具体类型，例如标准库中的 std::ops::Add
    type A;
    type B;
    fn contains(&self, a: &Self::A, b: &Self::B) -> bool;
}

fn difference<C: Container>(container: &C) {}

struct Counter {}

#[cfg(test)]
mod tests {
    use std::ops::Add;

    #[test]
    fn method() {}

    #[derive(Debug, PartialEq)]
    struct Point {
        x: i32,
        y: i32,
    }

    impl Add for Point {
        type Output = Point;
        fn add(self, other: Point) -> Point {
            Point {
                x: self.x + other.x,
                y: self.y + other.y,
            }
        }
    }

    #[derive(Debug)]
    struct Millimeters(u32);

    struct Meters(u32);

    impl Add<Meters> for Millimeters {
        type Output = Millimeters;

        fn add(self, other: Meters) -> Millimeters {
            Millimeters(self.0 + (other.0))
        }
    }

    #[test]
    fn add_other() {
        println!("{:?}", Millimeters(1).add(Meters(12)))
    }
}
